package kassiopeia.plugin.crawler.processor;

import kassiopeia.plugin.Event;
import kassiopeia.plugin.PluginException;
import kassiopeia.plugin.ProcessorPlugin;
import kassiopeia.plugin.crawler.processor.config.Configuration;
import kassiopeia.plugin.crawler.processor.config.Item;
import kassiopeia.plugin.crawler.processor.config.Serializer;
import org.apache.log4j.Logger;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

public class CrawlerProcessorPlugin extends ProcessorPlugin {

    private Configuration configuration;
    private Logger logger = Logger.getLogger(CrawlerProcessorPlugin.class);
    private int ALERT_LEVEL;
    private String LEVEL_HEADER_NAME = "LEVEL";
    private String ITEM_ID_HEADER_NAME = "ITEM_ID";
    private String OUTPUT = "output";

    @Override
    public void beforeTask() {
        String configFileName = getClass().getClassLoader().getResource("config.xml").getFile();
        try {
            configuration = Serializer.fromXML(new FileInputStream(configFileName));
            logger.info("configuration read:\n" + configuration);
        } catch (FileNotFoundException ex) {
            throw new PluginException(ex);
        }
    }

    @Override
    public void process(Event event) {
        logger.debug("Processing event: " + event);
        String body = getNotNullableEventBody(event, String.class);
        List<Match> matches = calculateMatch(body);
        for (Match match : matches) {
            if (match.getLevel() > ALERT_LEVEL) {
                alert(match);
            }
            event.setHeader(LEVEL_HEADER_NAME, match.getLevel());
            event.setHeader(ITEM_ID_HEADER_NAME, match.getItem().getId());
            getContext().sendLocally(event, OUTPUT);
        }
        logger.debug("Processing done with event " + event);
    }

    private List<Match> calculateMatch(String body) {
        List<Match> matches = new ArrayList<Match>();
        for (Item item : configuration.getItems()) {
            int level = calculateLevel(item, body);
            matches.add(new Match(level, item));
        }
        return matches;
    }

    private int calculateLevel(Item item, String body) {
        int found = 0;
        body = body.toUpperCase();
        for (String keyword : item.getKeywords()) {
            if (body.contains(keyword.toUpperCase())) {
                found++;
            }
        }
        return (int) (((double) found) / ((double) item.getKeywords().size()) * 100);
    }

    private void alert(Match match) {
        logger.warn(match.toString());
        getContext().alert(match.toString());
    }

}
